package com.sz.wallet_demo.filter;

import com.sz.wallet_demo.config.CurrContextHolder;
import com.sz.wallet_demo.model.User;
import com.sz.wallet_demo.utils.RedisCache;
import com.sz.wallet_demo.vo.CurrVo;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author Ts-SuSu
 * @date 2023/9/2 8:29
 * @Description token拦截器
 */

@Component
public class TokenFilter extends OncePerRequestFilter {

    /**
     * 放行接口
     */
    private static final List<String> RELEASE_INTERFACE =
            Arrays.asList(
                    "/user/login",
                    "/swagger-ui.html",
                    "/doc.html",
                    "/webjars/**",
                    "/v2/**",
                    "/swagger-resources");

    private RedisCache redisCache;

    public TokenFilter(RedisCache redisCache) {
        this.redisCache = redisCache;

    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取请求头token
        String token = request.getHeader("Authorization");
        // 获取当前请求的接口路径
        String requestURI = request.getRequestURI();
        boolean flag = CheckAuthority(requestURI);
        if (flag) {
            filterChain.doFilter(request, response);
            return;
        }
        if (!StringUtils.hasText(token)) {
            throw new RuntimeException("参数错误，token不能为空");
        }
        //查redis
        String tokenRedisKey = "auth:" + token;
        User user = (User) redisCache.get(tokenRedisKey);
        if (Objects.isNull(user)) {
            throw new RuntimeException("用户未登录或已失效");
        }
        //将redis中的user数据存入ThreadLocal中
        CurrVo currVo = new CurrVo();
        currVo.setUser(user);
        currVo.setToken(token);
        CurrContextHolder.setUser(currVo);
        //放行
        filterChain.doFilter(request, response);
    }

    /**
     * 判断是否包含放行接口*
     *
     * @param requestUrl
     * @return true:包含 false:不包含
     */
    public boolean CheckAuthority(String requestUrl) {
        for (String interfacePath : RELEASE_INTERFACE) {
            // 判断请求路径与接口路径是否相等
            if (requestUrl.equals(interfacePath)) {
                return true;
            }
            // 判断接口路径是否包含通配符 *
            if (interfacePath.contains("*")) {
                // 将接口路径中的通配符 * 替换为正则表达式中的 .*
                String regex = interfacePath.replace("*", ".*");
                // 判断请求路径是否与正则表达式匹配
                if (requestUrl.matches(regex)) {
                    return true;
                }
            }
        }
        return false;
    }
}
